home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-03-09 | 7.6 KB | 326 lines | [TEXT/MSET] |
- \ Dialog+ - MRH April 87.
-
- \ This subclass of Dialog implements modeless dialogs, popup menu support,
- \ and other things.
-
- \ Nov 87 mrh Added enabling and disabling of dialogs.
- \ July 91 mrh Migrated some methods to Dialog (now in a module).
- \ Mar 95 mrh Event handlers no longer return a boolean
-
-
- need dialog
-
- objPtr DLG-CHAIN \ Head of chain of open dialogs. When
- \ DialogSelect returns TRUE, we search this
- \ chain to find which which one was hit.
-
- objPtr ACTIVE_DLG
- objPtr THIS_DLG \ These 3 objPtrs will be set to class Dialog+.
-
- var DPTR clear: dptr
-
- handle TEHDL
- \ This is a copy of the textH field of a dialog, if a dialog window
- \ is frontmost. Nil otherwise. This allows us to call TEidle in the
- \ main event loop when necessary, as required for the insertion point
- \ to blink.
-
- handle SaveTEhdl \ Saves TEhdl while we're suspended
-
- $ A0 constant TEXTH_OFFS
-
- : SET_TEHDL \ ( wnd-ptr -- )
- \ wnd-ptr is the (relative) address of the dialog's window,
- \ which is the same as the address of the dialog record itself,
- \ as the window field comes first. The corresponding
- \ absolute address is contained in the ivar dlgPtr.
-
- textH_offs + @ ?dup IF put: teHdl ELSE clear: teHdl THEN ;
-
-
- :class DIALOG+ super{ dialog }
- record
- { ptr F-LINK \ Forward link - ^dlg
- ptr B-LINK \ Backward link ditto
- bool ENABLED?
- ptr PUM-LINK \ Link to any pop-up menus
- }
-
- ' dlg-chain set_to_class dialog+
- ' active_dlg set_to_class dialog+
- ' this_dlg set_to_class dialog+
-
-
- :m F-LINK: \ ( -- ^dlg )
- get: f-link ;m
-
- \ ( ^dlg -- )
- :m SET-F-LINK: put: f-link ;m
- :m SET-B-LINK: put: b-link ;m
-
- \ ( -- ^dlg )
- :m PUM-LINK: get: PUM-link ;m
- :m SET-PUM-LINK: put: PUM-link ;m
-
-
- :m GETNEW:
- nil?: dlgPtr 0EXIT \ Out if open already
- dlg-chain put: f-link
- dlg-chain nilP =
- NIF ^base set-b-link: dlg-chain THEN
- ^base -> dlg-chain clear: b-link
- getnew: super
- get: dlgPtr set_teHdl
- 0 -> actW ;m \ Front window is a dialog, not a Mops window
-
-
- :m CLOSE:
- nil?: dlgPtr ?EXIT \ Out if closed already
- nil?: f-link
- NIF get: b-link get: f-link set-b-link: dialog+ THEN
- nil?: b-link
- NIF get: f-link get: b-link set-f-link: dialog+
- ELSE get: f-link -> dlg-chain
- THEN
- clear: teHdl nilP -> active_dlg close: super ;m
-
- :m EXEC: \ ( index -- )
- get: enabled? if exec: super else drop then ;m
-
- :m ENABLE: true put: enabled? ;m
-
- :m DISABLE: false put: enabled? ;m
-
- :m ENABLED?: get: enabled? ;m
-
-
- :m CLASSINIT: enable: self ;m
-
- :m DUMP:
- ^base .h 3 spaces nil?: dlgPtr if ." not " then ." open"
- 3 spaces get: enabled?
- if ." enabled" else ." disabled" then cr
- get: f-link ." f-link " .h get: b-link ." b-link " .h
- ." dlgPtr " get: dlgPtr .h cr
- dlg-chain ." dlg-chain " .h ;m
-
- ;class
-
- \ =====================================
-
- : FIND-DLG { dlptr -- b }
- dlg-chain -> this_dlg
- BEGIN
- this_dlg nilP = IF false EXIT THEN
- dlgPtr: this_dlg dlptr =
- IF true EXIT THEN
- f-link: this_dlg -> this_dlg
- AGAIN ;
-
-
- : DLGPORT \ Sets the current grafport to the current dialog.
- dlgPtr: this_dlg call setPort ;
-
-
- 0 value EXEC?
-
- : MLD-EVT
- word0 fEvent addr: dptr addr: theItem
- call DialogSelect i->l 0<> -> exec?
- get: dptr find-dlg 0EXIT
- exec? 0EXIT
- get: theItem 1- exec: this_dlg ;
-
-
- : CLOSE-DLG \ ( dlptr -- )
- find-dlg 0exit
- close: this_dlg ;
-
- : IS_DLG_EVT? \ ( -- b )
- word0 fevent call IsDialogEvent i->l ;
-
-
- \ ?TEidle calls TEidle if a modeless dialog with a TE field is current.
- \ We have to do this at regular intervals in order to get the insertion
- \ point to blink. If the call is needed, the handle TEhdl won't be nil,
- \ and will be a handle to the TE field. We arrange for this word to be
- \ called regularly by having our handler for null events make the call.
-
- : ?TEIDLE
- nil?: teHdl ?EXIT
- get: teHdl call TEidle ;
-
- : UPD-EV appWind? 0EXIT upd-evt ;
-
- : ACTV-EV appWind? 0EXIT actv-evt ;
-
- : NULL-EV ?TEidle null-evt ;
-
- : OS-EV \ When the system sends us Suspend and Resume events, it doesn't
- \ deactivate/activate any windows. We have to handle it
- \ ourselves. Here we look after non-modal dialog windows.
- \ Ordinary windows are handled by OS-EVT in file Event.
- OS-evt
- suspend?
- IF get: TEhdl put: saveTEhdl
- nil?: TEhdl
- NIF get: TEhdl call TEDeactivate clear: TEhdl THEN
- EXIT
- THEN
- resume?
- IF get: saveTEhdl put: TEhdl
- nil?: TEhdl NIF get: TEhdl call TEActivate THEN
- THEN ;
-
-
- : ERR 60 beep abort ;
-
- \ We set the drag limit for dialogs at the time the drag is done - this
- \ allows the screen size to change while a dialog is up!
-
- rect DRAG-LIMIT
-
- : SET_DRAG-LIMIT
- screenbits put: drag-limit 10 10 inset: drag-limit ;
-
-
- : ENB? \ ( -- b ) Returns true if WND corresponds to an enabled
- \ dialog.
- wnd find-dlg NIF false exit THEN
- enabled?: this_dlg ;
-
- : ?SELECT \ Selects the dialog corresponding to WND, if enabled.
- enb? 0EXIT
- wnd call SelectWindow ;
-
- : ?DRAG \ Drags the dialog (maybe only if enabled).
- enb? 0EXIT \ Include if you don't want disabled dlgs draggable
- set_drag-limit
- wnd where: fEvent
- addr: drag-limit call DragWindow ;
-
- : ?CLOSE \ Handles a click in the close box if enabled.
- enb? 0EXIT
- wnd dup >r word0 r>
- where: fEvent call TrackGoAway word0
- IF close-dlg ELSE drop THEN ;
-
-
- : MLD-MOUSE-EVT \ ( rgn -- )
- \ Handles a click on a dialog window that was not reported
- \ as a dialog event. It could be select, drag, grow or close.
- \ If the dialog is not enabled, we ignore the click.
-
- SELECT{
- 3 IS{ ?select }END
- 4 IS{ ?drag }END
- 5 IS{ ( A dialog box can't grow! ) }END
- 6 IS{ ?close }END
- DEFAULT{ err
- }SELECT ;
-
-
- : MOUSE-EVT+MLD \ ( -- )
- is_dlg_evt? IF MLD-evt EXIT THEN
- when: fEvent put: theMouse \ update click interval
- where: fEvent find-window -> wnd
- wnd windowKind 2 = ( Dialog window? )
- IF MLD-mouse-evt
- ELSE (mouse-evt)
- THEN ;
-
-
- : KEY-EVT+MLD \ ( -- )
- active_dlg nilP =
- NIF key: active_dlg 0EXIT \ out if already handled
- mods: fEvent $ 100 and
- NIF MLD-evt EXIT THEN
- THEN
- key-evt ;
-
-
- : UPD-EVT+MLD \ ( -- )
- is_dlg_evt?
- IF MLD-evt
- drawBold: this_dlg EXIT
- THEN
- msg: fEvent -> wnd
- upd-ev ;
-
-
- : ACTV-EVT+MLD \ ( -- )
- msg: fEvent -> wnd
- wnd windowKind 2 =
- IF mods: fEvent 01 and
- IF \ activate
- wnd set_TEhdl
- msg: fEvent find-dlg
- IF this_dlg -> active_dlg
- ELSE nilP -> active_dlg
- THEN
- ELSE \ deactivate
- clear: TEhdl nilP -> active_dlg
- THEN
- is_dlg_evt? IF MLD-evt EXIT THEN
- THEN
- actv-ev ;
-
-
- : +MODELESS
- XTS{ null-ev mouse-evt+mld null-ev key-evt+mld
- null-ev key-evt+mld upd-evt+mld disk-evt
- actv-evt+mld null-ev null-ev null-ev
- null-ev null-ev null-ev OS-ev
- null-ev null-ev null-ev null-ev
- null-ev null-ev null-ev HL-evt }
- put: fEvent
- \ ['] ?TEidle -> TEidle
- sleepticks 0< IF 20 ELSE sleepticks 20 min THEN
- -> sleepticks ;
-
-
- endload
-
- \ TESTING:
-
- \ ================== "MLD test" dialog box ==========================
-
- 6 dialog+ D1 2 setbold: d1
- 4 dialog+ D2
-
-
- : QQQ 20 beep ;
- : WWW 1 beep ;
- : ZZZ ." useritem hit" cr ;
-
-
- : USER->TEMPRECT \ ( hdl w:item# -- b )
- i->l swap find-dlg
- IF itemHandle: this_dlg drop true
- ELSE ( item# ) drop false
- THEN ;
-
-
- :proc DRAW_USER
- user->tempRect
- IF " Hello" tempRect 1 makeint call textBox
- dropShadow: tempRect
- THEN ;proc
-
-
-
- : CLOSE1 close: d1 ;
- : CLOSE2 close: d2 ;
-
- XTS{ qqq www close1 togitem zzz zzz } 300 init: d1
- XTS{ qqq www close2 zzz } 301 init: d2
-
- : GO
- " MLDtest.rsrc" openresfile \ ***
- +modeless
- getnew: d1 getnew: d2
- ['] draw_user dup 6 setUserProc: d1 dup 5 setUserProc: d1
- 4 setUserProc: d2 ;
-
- : zz close: d1 close: d2 -modeless ;
-